package model

import (
    _ "github.com/go-sql-driver/mysql"
    "database/sql"
    "errors"
    "gitee.com/zwx784533/zwx2018/config"
    "time"
    "github.com/garyburd/redigo/redis"
    "fmt"
    "gitee.com/zwx784533/zwx2018/app"
)
// redis 连接池
var redisPoolMap map[string]*redis.Pool
var dbMap map[string]*sql.DB
func init()  {
    // map 要通过 make 创建才能使用
    redisPoolMap = make(map[string]*redis.Pool)
    dbMap = make(map[string]*sql.DB)
}

// 获取一个 db 连接
func GetDb(dbName string) (*sql.DB, error) {
    db, ok := dbMap[dbName]
    if ok {
        // 存在连接，直接返回
        return db,nil
    } else {
        dbConfig, ok := config.DB[dbName]
        if ok {
            // 连接不存在，初始化一个
            return newDb(dbConfig)
        } else {
            // 没有在配置文件中配置该数据库
            err := errors.New("unknown database: " + dbName)
            go app.Error(err)
            return nil, err
        }
    }
}

// 根据 name 获取一个连接池
func GetRedisPool(name string) (*redis.Pool, error)  {
    pool, ok := redisPoolMap[name]
    if ok {
        return pool, nil
    } else {
        redisConf, ok := config.RedisConf[name]
        if ok {
            pool = newRedisPool(redisConf)
            return pool,nil
        }
    }
    return nil, errors.New("unknown redis: " + name)
}

// 初始化一个 db 连接
func newDb(dbConfig config.DbConfig) (*sql.DB, error)  {
    db, err := sql.Open("mysql", dbConfig.Url)
    if err != nil {
        go app.Error(err)
        return nil, err
    }
    // 设置最大空闲连接数
    db.SetMaxIdleConns(dbConfig.MaxIdleConns)
    // 设置最大活跃连接数
    db.SetMaxOpenConns(dbConfig.MaxOpenConns)
    // 把该连接保存进 map 中
    dbMap[dbConfig.Name] = db
    return db, nil
}

//初始化一个 redis 连接池
func newRedisPool(redisConfig config.RedisConfig) (*redis.Pool)  {
    redisPool := &redis.Pool{
        MaxIdle:     redisConfig.MaxIdle,
        MaxActive:   redisConfig.MaxActive,
        IdleTimeout: 60 * time.Second,
        Dial: func() (redis.Conn, error) {
            c, err := redis.Dial("tcp", fmt.Sprintf("%s:%d", redisConfig.Host, redisConfig.Port))
            if err != nil {
                return nil, err
            }
            if redisConfig.Auth != "" {
                if _, err := c.Do("AUTH", redisConfig.Auth); err != nil {
                    c.Close()
                    return nil, err
                }
            }
            return c, err
        },
    }
    redisPoolMap[redisConfig.Name] = redisPool
    return  redisPool
}

